package il.ac.biu.cs.grossmm.api.simple;

import il.ac.biu.cs.grossmm.api.flow.Status;
import il.ac.biu.cs.grossmm.api.keys.Key;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * Provides a base for implementation of <tt>InternalSubscription</tt>.
 * The subclass should implement the both <tt>getPayload</tt> methods
 * to convert from internal data representation to a MIME object.
 */
public abstract class InternalSubscriptionBase implements InternalSubscription
{
	/**
	 * The key which refers to the resource for this internal subscription
	 */
	protected final Key key;
	
	/**
	 * Current internal subscription status
	 */
	protected Status status = Status.INIT;
	
	/**
	 * Set of sip subscriptions backed by this internal subscription
	 */
	protected final Set<SipSubscription> sipSubs = new TrackedHashSet();
	

	class TrackedHashSet extends HashSet<SipSubscription>  {
		/**
		 *  Serial id
		 */
		private static final long serialVersionUID = 5788787658077057457L;

		@Override
		public boolean remove(Object o) {
			boolean b = super.remove(o);
			if( isEmpty() ) { 
				close();
			}
			
			return b;
		}
		
		@Override
		public Iterator<SipSubscription> iterator() {
			return new Iter(super.iterator());
		}
		
		class Iter implements Iterator<SipSubscription> {
			final Iterator<SipSubscription> it;
			Iter(Iterator<SipSubscription> it) {
				this.it=it;
			}
			public boolean hasNext() {
				return it.hasNext();
			}
			public SipSubscription next() {
				return it.next();
			}
			public void remove() {
				it.remove();
				if( isEmpty() )
					close();
			}
		}
	}
	
	/**
	 * Constructs a new internal subscription by its key
	 * @param key the key which refers to the resource for this internal subscription
	 */
	public InternalSubscriptionBase(Key key) {
		this.key = key;
	}

	public void addSipSubscription(SipSubscription subscription) {
		sipSubs.add(subscription);
		subscription.setInternalSubscription(this);
	}
	
	public void removeSipSubscripttion(SipSubscription subscription) {
		sipSubs.remove(subscription);
		subscription.setInternalSubscription(null);
	}

	public Key getKey() {
		return key;
	}

	public Set<SipSubscription> getSipSubscriptrions() {
		return sipSubs;
	}

	public Status getStatus() {
		return status;
	}

	abstract protected void close();

}
